#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <vector>
using std::vector;
#include "Const.h"
#include "SortFactory.h"
#include "Config.h"
#include "TestSort.h"

TestSort::~TestSort()
{
	if (m_list) {
		delete []m_list;
		m_list = 0;
	}
}

void TestSort::Init(int num)
{
	m_num = num;
	m_list = new int[m_num];
}

void TestSort::CreateData()
{
	for (int i=0; i<m_num; ++i) {
		m_list[i] = rand() % m_num*10;
	}					
}

void TestSort::ReleaseData()
{
	memset(m_list, 0, m_num);
}

void TestSort::Print()
{
	for(int i=0; i<m_num; ++i) {
		printf("%d ", m_list[i]);				
	}	
	printf("\n");
}

void TestSort::ExecuteSingle(Sort* pSort, const Property& obj)
{
	struct timeval start, stop;
	unsigned long duration;
	if (obj.m_iter) {
		CreateData();
		
		gettimeofday(&start, NULL);
		pSort->Iterative(m_list, m_num);
		gettimeofday(&stop, NULL);
		duration = (stop.tv_sec - start.tv_sec)*1000000 + (stop.tv_usec - start.tv_usec);
		printf("iteration cost time %lu usec--------------------\n", duration);			

		if (obj.m_print) Print();
		ReleaseData();												
	}

	if (obj.m_recur) {
		CreateData();

		gettimeofday(&start, NULL);
		pSort->Recursive(m_list, m_num);
		gettimeofday(&stop, NULL);
		duration = (stop.tv_sec - start.tv_sec)*1000000 + (stop.tv_usec - start.tv_usec);
		printf("recursion cost time %lu usec--------------------\n", duration);			

		if (obj.m_print) Print();
		ReleaseData();												
	}
}

void TestSort::ExecuteInsertion(const PropInsertion& prop)
{
	Sort* pSort = 0;	

	if (prop.m_direct.m_enable) {
		pSort = SortFactory::Instance(C_STR_INSERTION_DIRECT);
		ExecuteSingle(pSort, prop.m_direct);
	}	

	if (prop.m_binary.m_enable) {
		pSort = SortFactory::Instance(C_STR_INSERTION_BINARY);
		ExecuteSingle(pSort, prop.m_binary);
	}	

	if (prop.m_shell.m_enable) {
		pSort = SortFactory::Instance(C_STR_INSERTION_SHELL);
		ExecuteSingle(pSort, prop.m_shell);
	}	
}

void TestSort::ExecuteSelection(const PropSelection& prop)
{
	Sort* pSort = 0;	

	if (prop.m_simple.m_enable) {
		pSort = SortFactory::Instance(C_STR_SELECTION_SIMPLE);
		ExecuteSingle(pSort, prop.m_simple);
	}	

	if (prop.m_heap.m_enable) {
		pSort = SortFactory::Instance(C_STR_SELECTION_HEAP);
		ExecuteSingle(pSort, prop.m_heap);
	}	
}

void TestSort::ExecuteSwap(const PropSwap& prop)
{
	Sort* pSort = 0;	

	if (prop.m_bubble.m_enable) {
		pSort = SortFactory::Instance(C_STR_SWAP_BUBBLE);
		ExecuteSingle(pSort, prop.m_bubble);
	}	

	if (prop.m_quick.m_enable) {
		pSort = SortFactory::Instance(C_STR_SWAP_QUICK);
		ExecuteSingle(pSort, prop.m_quick);
	}	
}

void TestSort::ExecuteMerge(const PropMerge& prop)
{
	Sort* pSort = 0;	

	if (prop.m_merge.m_enable) {
		pSort = SortFactory::Instance(C_STR_MERGE);
		ExecuteSingle(pSort, prop.m_merge);
	}	
}

void TestSort::Execute()
{
	const PropInsertion insertion = Config::Instance()->GetPropInsertion();
	if (insertion.m_enable)	{
		ExecuteInsertion(insertion);				
	}	

	const PropSelection selection = Config::Instance()->GetPropSelection();
	if (selection.m_enable) {
		ExecuteSelection(selection);	
	}	

	const PropSwap swap = Config::Instance()->GetPropSwap();
	if (swap.m_enable) {
		ExecuteSwap(swap);
	}	

	const PropMerge merge = Config::Instance()->GetPropMerge();
	if (merge.m_enable) {
		ExecuteMerge(merge);
	}										
}
